#保留字
keywords = ['and','array','begin','bool','call','case','char','constant',
'dim','do','else','end','false','for','if','input','integer','not',
'of','or','output','procedure','program','read','real','repeat','set',
'stop','then','to','true','until','var','while','write']
#制表符
signs = ['*','+','-',',',';','=','(',')','[',']']
#单词集
code_list = ['null','and','array','begin','bool','call','case','char',
'constant','dim','do','else','end','false','for','if','input','integer','not',
'of','or','output','procedure','program','read','real','repeat','set',
'stop','then','to','true','until','var','while','write','ID','INT','CHAR',
'(',')','*','*/','+',',','-','.','..','/','/*',':',':=',';','<','<=','<>',
'=','>','>=','[',']']

src_code = ''
result_list = []
list = []

#读取文档
def read_file(filepath):
    src_code = ''
    for line in open(filepath,'r'):
        src_code += line
    return src_code

#判断字符
def is_letter(char):
    if char >= 'a' and char <= 'z' or char >= 'A' and char <= 'Z':
        return True
    else:
        return False
#判断数字
def is_digit(char):
    if char >= '0' and char <= '9':
        return True
    else:
        return False

#返回判断列表
def add_result(*args):
    code = str(code_list.index(str(args[0])))
    if len(args)>1:
        result_list.append('( '+code+', ' + str(args[1]) +' )')
        list.append(int(code))
    else:
        result_list.append('( '+code+', - )')
        list.append(int(code))
    return result_list

def src_code_to_result_list(src_code):
    i=0
    count=1
    words = []
    line_count = 1
    #注释判断
    while i < len(src_code):
        if src_code[i] == '/':
            if i+1< len(src_code) and src_code[i+1] == '*':
                i+=2
                while src_code[i] != '*' or src_code[i+1] != '/':
                    i+=1
                    if i + 1 == len(src_code):
                        # result_list.clear()
                        result_list.append('错误: 注释缺失" */ "(行号：%d)'%line_count)
                        return
                i+=2
            else:
                add_result('/')
                i+=1
                #制表符判断
        elif src_code[i] == ':':
            if i+1< len(src_code) and src_code[i+1] == '=':
                add_result(':=')
                i+=2
            else:
                add_result(':')
                i+=1
        elif src_code[i] == '.':
            if i+1< len(src_code) and src_code[i+1] == '.':
                add_result('..')
                i+=2
            else:
                add_result('.')
                i+=1
        elif src_code[i] == '<':
            if i+1< len(src_code) and src_code[i+1] == '=':
                add_result('<=')
                i+=2
            elif src_code[i+1] == '>':
                add_result('<>')
                i+=2
            else:
                add_result('<')
                i+=1
        elif src_code[i] == '>':
            if i+1< len(src_code) and src_code[i+1] == '=':
                add_result('>=')
                i+=2
            else:
                add_result('>')
                i+=1
        elif src_code[i] in signs:
            add_result(src_code[i])
            i+=1
        
        elif is_letter(src_code[i]):
            word =''
            while i < len(src_code) and ( is_letter(src_code[i]) or is_digit(src_code[i]) ) :
                word += src_code[i]
                i+=1
            if word in keywords:
                add_result(word)
            else:
                if word in words:
                    index = words.index(word)
                    add_result('ID',index)
                else:
                    words.append(word)
                    add_result('ID',count)
                    count+=1
        elif is_digit(src_code[i]):
            digit = ''
            while is_digit(src_code[i]):
                digit += src_code[i]
                i+=1
            if digit in words:
                index = words.index(digit)
                add_result('INT',index)
            else:
                words.append(digit)
                add_result('INT',count)
                count+=1
                #字符常量判断
        elif src_code[i] == '\'':
            i+=1
            char = ''
            while src_code[i] != '\'':
                char += src_code[i]
                i+=1
                if i == len(src_code):

                    result_list.append('错误:单引号缺右引号(行号：%d)'%line_count)
                    return
            if char in words:
                index = words.index(char)
                add_result('CHAR',index)
            else:
                words.append(char)
                add_result('CHAR',count)
                count+=1
            i+=1
        elif src_code[i] == '\n' or src_code[i] == '\r':
                line_count+=1
                i+=1
        elif src_code[i] == ' ':
            i+=1
            #非法字符报错
        else:           
            result_list.append('错误：非法字符:{}(行号:{})'.format(src_code[i],line_count))
            i+=1
    return list

#输出结果
def output():
    output = ''
    for i in range(0,len(result_list)):
        output += result_list[i] + '  '
        if (i+1)%5 == 0:
            output += '\n'
    print('词法分析结果：')
    print(output)
    return 
#程序作者
def print_info():
    print('-----------------------------------------------------')
    print('作者：编译原理第一组 —— 杨洁龙、曾海龙、朱炜业、曾靖强')
    print('-----------------------------------------------------')


      
if __name__ == '__main__':
    print_info()
    choice = 1
    while choice == 1 :       
        filename = input('请输入测试程序名：')
        src_code = read_file(filename)
        src_code_to_result_list(src_code)
        output()
        result_list.clear()
        choice = int(input('''是否还要继续测试？
              是: 1
              否: 0\n'''))
    